﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FBroSharp;
using FBroSharp.Lib;
using FBroSharp.Value;
using FBroSharp.DataType;
using FBroSharp.Const;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using Newtonsoft.Json;

namespace FBroBrowserAutomation
{
    public partial class Form1 : Form
    {
        // 浏览器用户标识
        private const string BROWSER_USER_FLAG = "weibo_scraper";

        // 采集的数据列表
        private List<WeiboHotSearchItem> _collectedData = new List<WeiboHotSearchItem>();

        // 是否正在采集
        private bool _isCollecting = false;

        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
            this.FormClosing += Form1_FormClosing;

            // 设置 EPPlus 许可证
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            UpdateStatus("准备创建浏览器...");
            CreateBrowser();
        }

        /// <summary>
        /// 创建浏览器实例
        /// </summary>
        private void CreateBrowser()
        {
            try
            {
                // 创建浏览器事件处理器
                BrowserEvent browserEvent = new BrowserEvent(this);

                // 配置窗口信息（嵌入到 Panel 中）
                FBroSharpWindowsInfo windowInfo = new FBroSharpWindowsInfo
                {
                    parent_window = panelBrowser.Handle, // ⚠️ 嵌入式浏览器
                    x = 0,
                    y = 0,
                    width = panelBrowser.Width,
                    height = panelBrowser.Height,
                    window_name = "微博热搜采集器"
                };

                // 配置浏览器设置
                FBroSharpBrowserSetting settings = new FBroSharpBrowserSetting();

                // 创建浏览器
                bool success = FBroSharpControl.CreatBrowser(
                    "https://weibo.com/newlogin?tabtype=search&gid=&openLoginLayer=0&url=",
                    windowInfo,
                    settings,
                    null,  // request_context
                    null,  // extra_info
                    browserEvent,
                    default, // ✅ event_control 使用 default（struct 类型）
                    BROWSER_USER_FLAG
                );

                if (success)
                {
                    UpdateStatus("浏览器创建成功，正在加载页面...");
                }
                else
                {
                    MessageBox.Show("浏览器创建失败！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"创建浏览器时出错：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 页面加载完成回调
        /// </summary>
        public void OnPageLoaded()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(OnPageLoaded));
                return;
            }

            btnStartCollect.Enabled = true;
        }

        /// <summary>
        /// 开始采集按钮点击
        /// </summary>
        private async void btnStartCollect_Click(object sender, EventArgs e)
        {
            if (_isCollecting)
            {
                MessageBox.Show("正在采集中，请稍候...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            try
            {
                _isCollecting = true;
                btnStartCollect.Enabled = false;
                btnExportCsv.Enabled = false;
                btnExportExcel.Enabled = false;

                UpdateStatus("正在采集微博热搜数据...");

                // 获取浏览器实例
                var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(BROWSER_USER_FLAG);
                if (browser == null || !browser.IsValid)
                {
                    MessageBox.Show("浏览器未就绪！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // 获取主框架
                var frame = browser.GetMainFrame();
                if (frame == null || !frame.IsValid)
                {
                    MessageBox.Show("无法获取浏览器主框架！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // 执行 JavaScript 采集数据并获取返回值
                string jsonResult = ExecuteJavaScriptAndGetResult(frame);

                if (!string.IsNullOrEmpty(jsonResult))
                {
                    // 解析 JSON 数据
                    ParseAndDisplayData(jsonResult);
                }
                else
                {
                    MessageBox.Show("未能从页面采集到数据，请稍后重试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show($"采集数据时出错：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                _isCollecting = false;
                btnStartCollect.Enabled = true;
                btnExportCsv.Enabled = _collectedData.Count > 0;
                btnExportExcel.Enabled = _collectedData.Count > 0;
            }
        }

        /// <summary>
        /// 执行 JavaScript 并获取返回结果
        /// </summary>
        private string ExecuteJavaScriptAndGetResult(IFBroSharpFrame frame)
        {
            try
            {
                // 创建 JS 回调实例
                FBroSharpJsCallbackSyn callback = new FBroSharpJsCallbackSyn();

                // JavaScript 代码：采集微博热搜数据
                string jsCode = @"
(function() {
    const hotItems = [];
    const titleLinks = document.querySelectorAll('a.HotTopic_tit_eS4fv');
    
    titleLinks.forEach((link) => {
        try {
            const outerContainer = link.closest('[class*=""HotItem""], [class*=""hottopic""]') || 
                                  link.parentElement.parentElement.parentElement;
            
            // 排名
            const rankEl = outerContainer.querySelector('[class*=""rank""]');
            const rankText = rankEl ? rankEl.textContent.trim() : '';
            
            // 标题和URL
            const title = link.textContent.trim();
            const url = link.href;
            
            // 热度数值
            let heat = '';
            const allTextNodes = Array.from(outerContainer.querySelectorAll('*'))
                .map(el => el.textContent.trim())
                .filter(text => /^\d+$/.test(text) && text.length > 3);
            
            if (allTextNodes.length > 0) {
                heat = allTextNodes[allTextNodes.length - 1];
            }
            
            // 标签
            let tag = '';
            const tagElements = outerContainer.querySelectorAll('[class*=""icon-text""], [class*=""HotTopic_""][class*=""tag""]');
            tagElements.forEach(el => {
                const text = el.textContent.trim();
                if (text && text.length <= 3 && ['热', '新', '沸', '荐', '爆'].includes(text)) {
                    tag = text;
                }
            });
            
            // 图片
            const imgEl = outerContainer.querySelector('img');
            const image = imgEl ? (imgEl.src || imgEl.getAttribute('data-src') || '') : '';
            
            hotItems.push({
                rank: rankText,
                title: title,
                url: url,
                heat: heat,
                tag: tag,
                image: image && !image.includes('hotRankTop') ? image : ''
            });
        } catch (e) {
            console.error('Error:', e);
        }
    });
    
    return JSON.stringify({
        timestamp: new Date().toISOString(),
        total: hotItems.length,
        items: hotItems
    });
})();
";

                Console.WriteLine("开始执行 JavaScript 采集数据...");

                // 执行 JavaScript（带返回值）
                frame.ExecuteJavaScriptToHasReturn(
                    jsCode,
                    default,
                    default,
                    callback
                );

                if (callback.help != null && callback.help.IsValid)
                {
                    // 等待执行结果（超时时间 15 秒）
                    callback.help.WaitEvent(15 * 1000);

                    // 检查是否有字符串数据返回
                    if (callback.help.HavStringData())
                    {
                        string jsonData = callback.help.GetStringData();
                        callback.help.ClearData();

                        Console.WriteLine($"✅ JavaScript 执行成功，返回数据长度：{jsonData?.Length ?? 0}");
                        return jsonData;
                    }
                    else
                    {
                        Console.WriteLine("❌ JavaScript 未返回字符串数据");
                    }
                }
                else
                {
                    Console.WriteLine("❌ JavaScript 回调帮助对象无效");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ 执行 JavaScript 失败：{ex.Message}");
                UpdateStatus($"❌ 执行 JavaScript 失败：{ex.Message}");
            }

            return null;
        }

        /// <summary>
        /// 解析 JSON 数据并显示
        /// </summary>
        private void ParseAndDisplayData(string jsonData)
        {
            try
            {
                // 解析 JSON
                var response = JsonConvert.DeserializeObject<WeiboDataResponse>(jsonData);

                if (response == null || response.items == null || response.items.Count == 0)
                {
                    MessageBox.Show("未能从页面解析到数据！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                // 清空旧数据
                _collectedData.Clear();

                // 转换为显示数据模型
                foreach (var item in response.items)
                {
                    _collectedData.Add(new WeiboHotSearchItem
                    {
                        Rank = item.rank,
                        Title = item.title,
                        Url = item.url,
                        Heat = item.heat,
                        Tag = item.tag,
                        ImageUrl = item.image,
                        CollectTime = DateTime.Now
                    });
                }

                // 显示到表格
                UpdateDataGrid();

                UpdateStatus($"✅ 采集完成！共采集 {_collectedData.Count} 条热搜数据");

                MessageBox.Show($"数据采集完成！\n共采集 {_collectedData.Count} 条热搜数据\n采集时间：{response.timestamp}",
                    "采集完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                string preview = jsonData != null && jsonData.Length > 200 
                    ? jsonData.Substring(0, 200) + "..." 
                    : (jsonData ?? "null");
                MessageBox.Show($"解析数据失败：{ex.Message}\n\n原始数据：\n{preview}",
                    "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                UpdateStatus($"❌ 解析数据失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新数据表格
        /// </summary>
        private void UpdateDataGrid()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(UpdateDataGrid));
                return;
            }

            dgvData.DataSource = null;
            dgvData.DataSource = _collectedData;

            // 设置列标题
            if (dgvData.Columns.Count > 0)
            {
                dgvData.Columns["Rank"].HeaderText = "排名";
                dgvData.Columns["Title"].HeaderText = "标题";
                dgvData.Columns["Url"].HeaderText = "链接";
                dgvData.Columns["Heat"].HeaderText = "热度值";
                dgvData.Columns["Tag"].HeaderText = "标签";
                dgvData.Columns["ImageUrl"].HeaderText = "图片链接";
                dgvData.Columns["CollectTime"].HeaderText = "采集时间";

                // 设置列宽
                dgvData.Columns["Rank"].Width = 60;
                dgvData.Columns["Title"].Width = 250;
                dgvData.Columns["Url"].Width = 200;
                dgvData.Columns["Heat"].Width = 100;
                dgvData.Columns["Tag"].Width = 60;
                dgvData.Columns["ImageUrl"].Width = 150;
                dgvData.Columns["CollectTime"].Width = 150;
            }
        }

        /// <summary>
        /// 导出 CSV
        /// </summary>
        private void btnExportCsv_Click(object sender, EventArgs e)
        {
            if (_collectedData.Count == 0)
            {
                MessageBox.Show("没有数据可导出！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            try
            {
                SaveFileDialog sfd = new SaveFileDialog
                {
                    Filter = "CSV 文件|*.csv",
                    FileName = $"微博热搜_{DateTime.Now:yyyyMMdd_HHmmss}.csv"
                };

                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    using (StreamWriter sw = new StreamWriter(sfd.FileName, false, Encoding.UTF8))
                    {
                        // 写入 BOM 标记（Excel 需要）
                        sw.WriteLine(WeiboHotSearchItem.CsvHeader());

                        foreach (var item in _collectedData)
                        {
                            sw.WriteLine(item.ToCsvLine());
                        }
                    }

                    MessageBox.Show($"CSV 导出成功！\n文件位置：{sfd.FileName}", "导出成功",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);

                    UpdateStatus($"✅ CSV 导出成功：{sfd.FileName}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导出 CSV 失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 导出 Excel
        /// </summary>
        private void btnExportExcel_Click(object sender, EventArgs e)
        {
            if (_collectedData.Count == 0)
            {
                MessageBox.Show("没有数据可导出！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            try
            {
                SaveFileDialog sfd = new SaveFileDialog
                {
                    Filter = "Excel 文件|*.xlsx",
                    FileName = $"微博热搜_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx"
                };

                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    using (ExcelPackage package = new ExcelPackage())
                    {
                        // 创建工作表
                        var worksheet = package.Workbook.Worksheets.Add("微博热搜");

                        // 写入表头
                        worksheet.Cells[1, 1].Value = "排名";
                        worksheet.Cells[1, 2].Value = "标题";
                        worksheet.Cells[1, 3].Value = "链接";
                        worksheet.Cells[1, 4].Value = "热度值";
                        worksheet.Cells[1, 5].Value = "标签";
                        worksheet.Cells[1, 6].Value = "图片链接";
                        worksheet.Cells[1, 7].Value = "采集时间";

                        // 设置表头样式
                        using (var range = worksheet.Cells[1, 1, 1, 7])
                        {
                            range.Style.Font.Bold = true;
                            range.Style.Fill.PatternType = ExcelFillStyle.Solid;
                            range.Style.Fill.BackgroundColor.SetColor(Color.LightGray);
                        }

                        // 写入数据
                        int row = 2;
                        foreach (var item in _collectedData)
                        {
                            worksheet.Cells[row, 1].Value = item.Rank;
                            worksheet.Cells[row, 2].Value = item.Title;
                            worksheet.Cells[row, 3].Value = item.Url;
                            worksheet.Cells[row, 4].Value = item.Heat;
                            worksheet.Cells[row, 5].Value = item.Tag;
                            worksheet.Cells[row, 6].Value = item.ImageUrl;
                            worksheet.Cells[row, 7].Value = item.CollectTime.ToString("yyyy-MM-dd HH:mm:ss");
                            row++;
                        }

                        // 自动调整列宽
                        worksheet.Cells.AutoFitColumns();

                        // 保存文件
                        FileInfo fileInfo = new FileInfo(sfd.FileName);
                        package.SaveAs(fileInfo);
                    }

                    MessageBox.Show($"Excel 导出成功！\n文件位置：{sfd.FileName}", "导出成功",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);

                    UpdateStatus($"✅ Excel 导出成功：{sfd.FileName}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导出 Excel 失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 刷新页面
        /// </summary>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(BROWSER_USER_FLAG);
                if (browser != null && browser.IsValid)
                {
                    browser.Reload();
                    UpdateStatus("正在刷新页面...");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"刷新页面失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 窗体大小调整
        /// </summary>
        private void Form1_Resize(object sender, EventArgs e)
        {
            ResizeEmbeddedBrowser();
        }

        /// <summary>
        /// 调整嵌入式浏览器大小
        /// </summary>
        private void ResizeEmbeddedBrowser()
        {
            try
            {
                var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(BROWSER_USER_FLAG);
                if (browser != null && browser.IsValid)
                {
                    browser.MoveWindow(0, 0, panelBrowser.Width, panelBrowser.Height, true);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"调整浏览器大小失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 窗体关闭
        /// </summary>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(BROWSER_USER_FLAG);
                if (browser != null && browser.IsValid)
                {
                    browser.CloseBrowser(true, true);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭浏览器失败：{ex.Message}");
            }
        }

        #region UI 更新方法（线程安全）

        public void UpdateStatus(string message)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(UpdateStatus), message);
                return;
            }

            lblStatus.Text = message;
            Console.WriteLine(message);
        }

        public void UpdateAddressBar(string url)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(UpdateAddressBar), url);
                return;
            }

            txtUrl.Text = url;
        }

        public void UpdateTitle(string title)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(UpdateTitle), title);
                return;
            }

            this.Text = $"微博热搜采集器 - {title}";
        }

        public void UpdateLoadingState(bool isLoading)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<bool>(UpdateLoadingState), isLoading);
                return;
            }

            btnRefresh.Enabled = !isLoading;
        }

        #endregion
    }
}
